﻿using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

//妈的，终于有点成形了。
//太乱，头都晕了。

namespace AGuang.WebTool {
    /// <summary>
    /// 接收客户端的传值
    /// </summary>
    public class Receiver {
        
        /// <summary>
        /// 接收客户端的传值(测试版),文本，数字，时间，数组，List及其派生类
        /// </summary>
        /// <typeparam name="T">包装成的类型</typeparam>
        public static T Get<T>() where T:new() {
            Type t = typeof(T);
            T o = new T();
            HttpRequest request=HttpContext.Current.Request;
            FieldInfo[] fieldInfos = t.GetFields();

            PropertyInfo[] propertyInfos = t.GetProperties();
            List<String> requestKeys = new List<String>();
            //属性
            foreach (PropertyInfo propertyInfo in propertyInfos) {
                if (propertyInfo.CanWrite&&propertyInfo.GetIndexParameters().Length==0) {
                    String name=propertyInfo.Name;
                    
                    Type pt = propertyInfo.PropertyType;//属性的类型

                    Type ptIenumerable = pt.GetInterface("ICollection");//用于判断是否为数组或集合
                    if (ptIenumerable != null) { //如果是数组集合
                        String[] str1s=request.Form.GetValues(name);
                        String[] str2s = request.QueryString.GetValues(name);
                        List<String> strs = new List<string>();
                        if(str1s==null && str2s==null) continue;
                        if (str1s != null) {
                            foreach (String item in str1s) strs.Add(item);
                        }
                        if (str2s != null) {
                            foreach (String item in str2s) strs.Add(item);
                        }
                        if (pt.IsArray) { //数组
                            propertyInfo.SetValue(o, GetArrayValues(pt, strs.ToArray()),null);
                        } else {
                            propertyInfo.SetValue(o, GetEnumerableValues(pt, strs.ToArray()),null);
                        }
                    } else {
                        String value=request[name];
                        if(value==null) continue;
                        propertyInfo.SetValue(o, ConvertType(pt, value),null);
                        
                    }
                    requestKeys.Add(name);
                }
            }
            //字段
            foreach (FieldInfo fieldInfo in fieldInfos) {
                if (fieldInfo.IsPublic){
                    if (fieldInfo.IsStatic) continue;
                    String name = fieldInfo.Name;
                    bool hasKey = false;
                    foreach (String key in requestKeys) {
                        if (key.ToLower() == name.ToLower()) {
                            hasKey = true;
                        }
                    }
                    if (hasKey) continue;
        
                    Type pt = fieldInfo.FieldType;//字段的类型
                    Type ptIenumerable = pt.GetInterface("ICollection");//用于判断是否为数组或集合
                    if (ptIenumerable != null) { //如果是数组集合
                        String[] str1s = request.Form.GetValues(name);
                        String[] str2s = request.QueryString.GetValues(name);
                        List<String> strs = new List<string>();
                        if (str1s != null) {
                            foreach (String item in str1s) strs.Add(item);
                        }
                        if (str2s != null) {
                            foreach (String item in str2s) strs.Add(item);
                        }
                        if (pt.IsArray) { //数组
                            fieldInfo.SetValue(o, GetArrayValues(pt, strs.ToArray()));
                        } else {
                            fieldInfo.SetValue(o, GetEnumerableValues(pt, strs.ToArray()));
                        }
                    } else {
                        String value = request[name];
                        if (value == null) continue;
                        fieldInfo.SetValue(o, ConvertType(pt, value));
                    }
                }
            }
            return o;
        }


        /// <summary>
        /// 将字符串数组转换为指定类型的数组
        /// </summary>
        /// <param name="arrayType">数组类型</param>
        /// <param name="values">字符串数组</param>
        private static Array GetArrayValues(Type arrayType,String[] values) {
            if (!arrayType.IsArray) return null;
            String arrayTypeName = arrayType.FullName;
            String itemTypeName = arrayTypeName.Substring(0, arrayTypeName.Length - 2);
            Type itemType = Type.GetType(itemTypeName);
            if (itemType == null) return null;
            if (itemType.IsArray) return null;
            Object objs = new Object[values.Length];
            ArrayList list = new ArrayList();
            foreach (String item in values) {
                Object obj = ConvertType(itemType, item);
                if (obj == null) continue;
                list.Add(obj);
            }
            return list.ToArray(itemType);
        }

        /// <summary>
        /// 将字符串数组转换为指定类型的集合
        /// </summary>
        /// <param name="type">集合类型</param>
        /// <param name="values">字符串数组</param>
        /// <returns></returns>
        private static IEnumerable GetEnumerableValues(Type type, String[] values) {
            Type itemType = null;
            if (type.IsGenericType) {
                Type[] genericTypes = type.GetGenericArguments();
                if (genericTypes.Length > 1) return null;
                itemType = genericTypes[0];
            } else itemType = typeof(Object);
            ArrayList list=new ArrayList();
            foreach (String item in values) {
                Object obj = ConvertType(itemType, item);
                if (obj == null) continue;
                list.Add(obj);
            }
            return (IEnumerable)Activator.CreateInstance(type, list.ToArray(itemType));
        }

        /// <summary>
        /// 将字符串转换为指定基本类型
        /// </summary>
        /// <param name="targetType">目标类型</param>
        /// <param name="value">字符串</param>
        /// <returns></returns>
        private static Object ConvertType(Type targetType, String value) {
            if (targetType.IsGenericType) {
                Type[] genericTypes = targetType.GetGenericArguments();
                if (genericTypes.Length > 1) return null;
                Type itemType = genericTypes[0];
                ConstructorInfo[] constructors = targetType.GetConstructors();
                if (constructors == null) return null;
                foreach (ConstructorInfo constructor in constructors) { //找出合适的构告函数
                    if(!constructor.IsPublic) continue;
                    if(constructor.IsStatic) continue;
                    ParameterInfo[] paramInfos = constructor.GetParameters();
                    if (paramInfos.Length != 1) return null;
                    ParameterInfo paramInfo = paramInfos[0];
                    if (paramInfo.ParameterType == itemType) {
                        Object[] parms={ ConvertType(itemType, value)};
                        return constructor.Invoke(parms);
                    }
                }
                return null;
            }

            Type interfaceType = targetType.GetInterface("IConvertible");
            if (interfaceType == null && targetType.Name != "Object") return null;
            try {
                return Convert.ChangeType(value, targetType);
            } catch (Exception) {
                return null;
            }
        }
    }
}
